Strict 
Import mojo.app
Import mojo.graphics
Import vector2d
Import diddy.collections
Import diddy
Import tween2
Import model

Class Ball implements IComparable
	Const restitution:Float = 1
	Const EXPLODE_DURATION:Int = 500
	
	public 
	Field velocity:Vector2d
	Field position:Vector2d
	
	Field number:Int = 0
	Field visible:Bool
	Field alive:Bool=true
	
	Field alpha:Float=1.0
	Field scale:Float=1.0
	Field rotate:Float=0.0
	
	private	
    Field mass:float
	Field radius:float
	Field radius2:float
	Field angularVel:float
	Field orientation:float = 45.0
	
	' Vectors in class for optimization
	Field mtd:Vector2d 
	Field delta:Vector2d
	Field v:Vector2d
	Field impulse:Vector2d
	Field tempVect2d:Vector2d
	
	Field collisionOffset:Int = 1 ' 10 each side of image (accounts for blur)
	
	Field img:GameImage = game.images.Find("yellowGuy")
	Field eye1:GameImage = game.images.Find("eyeBall")
	Field eye2:GameImage = game.images.Find("eyeBall")
	
	Field explodeAlphaTween:Tween2= New Tween2(Tween2.Cubic.EaseIn,1,0,EXPLODE_DURATION)
	Field explodeScaleTween:Tween2= New Tween2(Tween2.Cubic.EaseIn,0,1,EXPLODE_DURATION)
	Field eyeWobbleTween:Tween2= New Tween2(Tween2.Elastic.EaseOut,3.0,0,1000)
	
	Field eyeBallMovementCounter:Int=0
	Field eyeBallMovement:Float=0
	
	Method New( x:float, y:float, radius:float)	
		init(x,y,radius,1)
	End
	
	Method New( x:float, y:float, radius:float, mass:float)	
		init(x,y,radius,mass)	
	End
		
	Method init:void( x:float, y:float, radius:float, mass:float)	
		self.velocity = new Vector2d(0, 0)
		self.position = new Vector2d(x, y)
		self.setMass(mass)
				
		self.rotate = 0
		
		self.visible = true
		self.alive=true
		
		self.mtd = new Vector2d()
		self.delta = new Vector2d()
		self.v = new Vector2d()
		self.impulse = new Vector2d()
		self.tempVect2d = new Vector2d()
		
		self.setRadius(radius)	
		self.scale=(self.radius2)/(img.w-collisionOffset)

		explodeAlphaTween.Rewind()
		explodeScaleTween.Rewind()

	End
	
	Method setRadius:void(radius:float) 
		self.radius = radius
		self.radius2 = radius*2
	End

	Method getRadius:float() 
		return radius
	End
	
	Method getRadius2:float() 
		return radius2
	End
	
	Method setMass:void(mass:float) 
		self.mass = mass
	End

	Method getMass:float() 
		return mass
	End
	
	Method Update:Void()		
		eyeBallMovementCounter+=1
		
		explodeAlphaTween.Update()
		explodeScaleTween.Update()
		eyeWobbleTween.Update()
		
		if(alive)
			position.x += velocity.x
			position.y += velocity.y	
		endif
		
		if(explodeAlphaTween.isActive)
			alpha=explodeAlphaTween.Value()
			scale=explodeScaleTween.Value()	
			rotate+=10
			eyeBallMovement=0
		elseif (eyeBallMovementCounter>100)
			eyeBallMovement=Rnd(5)-2.5
			eyeBallMovementCounter=0
		endif
		
		if(alive=false and explodeAlphaTween.isActive=false)
			visible=false
		endif	

	End
	
	Method Draw:Void()
		if(visible)
		'	SetColor(255,0,0)
		'	DrawOval( position.x-radius, position.y-radius, radius*2, radius*2)
			PushMatrix
				
			Translate(position.x, position.y)
	
			SetAlpha(alpha)
			Scale(scale, scale)
			Rotate(rotate)
			img.Draw(0, 0)
			SetColor(255,255,255)
			eye1.Draw(int(-13.0+eyeBallMovement),int(-12.0+eyeWobbleTween.Value()))
			eye2.Draw(int(13.0+eyeBallMovement),int(-12.0+eyeWobbleTween.Value()))
				
			_model.font.DrawText( number, 0, -10, AngelFont.ALIGN_CENTER)
			PopMatrix
			SetAlpha(1)
		End
	End
	
	Method Kill:void()	
		explodeScaleTween.SetValue(scale,0)
		explodeAlphaTween.Start()
		explodeScaleTween.Start()		
		alive=false
	End
	
	Method resolveCollision:void(ball:Ball)

		' get the mtd
		delta = position.subtract(ball.position, delta)
		Local r:float = getRadius() + ball.getRadius()
		Local dist2:float = delta.dot(delta)

		if (dist2 > r*r)
		 return ' they aren't colliding
		endif

		Local d:float = delta.getLength()
		
		if (d <> 0.0)		
			mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d, mtd) ' minimum translation distance to push balls apart after intersecting		
		else ' Special case. Balls are exactly on top of eachother.  Don't want to divide by zero.		
			d = ball.getRadius() + getRadius() - 1.0
			delta.setX(ball.getRadius() + getRadius())
			delta.setY( 0.0)

			mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d, mtd)
		endif

		' resolve intersection
		Local im1:float = 1 / getMass() ' inverse mass quantities
		Local im2:float = 1 / ball.getMass()

		' push-pull them apart
		position = position.add(mtd.multiply(im1 / (im1 + im2), tempVect2d), position)
		ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2), tempVect2d), ball.position)

		' impact speed
		v  = self.velocity.subtract(ball.velocity, v)
		Local vn:float = v.dot(mtd.normalize())

		
		' sphere intersecting but moving away from each other already
		if (vn > 0.0)
			return
		endif

		' collision impulse
		Local i:float = (-(1.0 + restitution) * vn) / (im1 + im2)
		impulse = mtd.multiply(i, impulse)

		' change in momentum
		self.velocity = self.velocity.add(impulse.multiply(im1, tempVect2d), self.velocity)
		ball.velocity = ball.velocity.subtract(impulse.multiply(im2, tempVect2d), ball.velocity)
		
		self.DoCollisionAnim()
		ball.DoCollisionAnim()

	End
	
	Method DoCollisionAnim:void()
		if(eyeWobbleTween.isActive<>true)
			eyeWobbleTween.Start()
		endif
	End
	
	Method CompareBool:Bool(o:Object)
		return Compare(self, o2) = 0
	End
	
	Method Compare:Int(o:Object) 
		Local ball:Ball = Ball(o)
		if (self.position.getX() - self.getRadius() > ball.position.getX() - ball.getRadius())		
			return 1
		elseif (self.position.getX() - self.getRadius() < ball.position.getX() - ball.getRadius())		
			return -1	
		else				
			return 0
		endif
	End

End